// Copyright 2012 Google Inc. All Rights Reserved.

package com.google.api.ads.common.lib.auth;

import com.google.api.ads.common.lib.utils.logging.AdsServiceLoggers;
import com.google.api.client.auth.oauth2.Credential;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.name.Named;

import java.io.IOException;

/**
 * OAuth2 helper functions.
 *
 * @author Adam Rogal
 */
public class OAuth2Helper {

  private final Long refreshWindowSeconds;
  private final AdsServiceLoggers adsServiceLoggers;

  /**
   * Constructor.
   *
   * @param adsServiceLoggers the loggers
   * @param refreshWindowSeconds the refresh window in seconds
   */
  @Inject
  public OAuth2Helper(AdsServiceLoggers adsServiceLoggers,
      @Named("oAuth2RefreshWindow") Long refreshWindowSeconds) {
    this.adsServiceLoggers = adsServiceLoggers;
    this.refreshWindowSeconds = refreshWindowSeconds;
  }

  /**
   * Refreshes the credential if within the refresh window.
   *
   * @throws IOException if there was an problem refreshing the token
   */
  public Credential refreshCredential(Credential credential) throws IOException {
    if (isCredentialRefreshable(credential)) {
      if (!callRefreshToken(credential)) {
        adsServiceLoggers.getLibLogger().warn(
            "OAuth2 token could not be refreshed. " +
            "Add a refreshListener to the Credential to capture this failure.");
      }
    }
    return credential;
  }

  /**
   * Calls the refreshToken method on credential.
   *
   * @throws IOException if the credential could not be refreshed.
   */
  @VisibleForTesting // For partial mocking.
  boolean callRefreshToken(Credential credential) throws IOException {
    return credential.refreshToken();
  }

  /**
   * Returns {@code true} if the credential can and should be refreshed.
   */
  @VisibleForTesting
  boolean isCredentialRefreshable(Credential credential) {
    return credential.getAccessToken() == null || credential.getExpiresInSeconds() != null
        && credential.getExpiresInSeconds() <= refreshWindowSeconds;
  }
}
